package com.zlsy.thread.lock;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * @author zhouliang
 * @date 2020/9/25 16:11
 * 自己使用AQS实现一个简单的线程协作器
 */
public class OneShotLatch {
    private final Sync sync = new Sync();

    public static void main(String[] args) throws InterruptedException {
        OneShotLatch oneShotLatch = new OneShotLatch();

        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorService.execute(() -> {
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(Thread.currentThread().getName() + "尝试获取latch，获取失败，那就等待；");
                        oneShotLatch.await();
                        System.out.println("开闸放行，继续运行！");
                    }
                });
                thread.start();
            });
        }
        Thread.sleep(5000);
        oneShotLatch.signal();

        executorService.shutdown();
    }

    /**
     * 直到有线程调用了signal。唤醒了所有的线程
     */
    public void signal() {
        sync.releaseShared(0);
    }

    /**
     * 起初门闩关闭，谁调用await方法，谁陷入阻塞；
     */
    public void await() {
        // -1 ==>> if (tryAcquireShared(arg) < 0);放入阻塞队列
        sync.acquireShared(0);
    }

    private class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected int tryAcquireShared(int arg) {
            //门闩=1代表被打开了，默认为0
            return getState() == 1 ? 1 : -1;
        }

        @Override
        protected boolean tryReleaseShared(int arg) {
            setState(1);
            return true;
        }
    }
}
